package com.ccys.app.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.ccys.app.feignClient.EmailFeignClient;
import com.ccys.app.service.ProfileService;
import com.ccys.common.enums.CodeEnum;
import com.ccys.common.third.mailGun.MailgunUtil;
import com.ccys.common.util.HtmlUtils;
import com.ccys.common.util.JedisUtil;
import com.ccys.common.util.Kit;
import com.ccys.common.util.PBKDF2Util;
import com.ccys.common.vo.ResponseResultApp;
import com.ccys.db.cache.UserUtil;
import com.ccys.db.dto.app.updateProfile.RedisMemberUpdateEmail;
import com.ccys.db.dto.app.updateProfile.UpdateProfileDto;
import com.ccys.db.dto.discount.MatchingPremiumCouponsDto;
import com.ccys.db.entity.TblCountry;
import com.ccys.db.entity.TblMember;
import com.ccys.db.enums.MemberIDCardTypeEnum;
import com.ccys.db.enums.RedisEnum;
import com.ccys.db.mapper.TblCountryMapper;
import com.ccys.db.mapper.TblMemberMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

/**
 * @program: WhiteCoat
 * @description: 个人信息接口
 * @author: ZhangJingCan
 * @create: 2024-02-02 14:38
 **/

@Service
public class ProfileServiceImpl implements ProfileService {

    @Resource
    private TblMemberMapper tblMemberMapper;

    /**
     * 远程调用邮件相关
     */
    @Autowired
    private EmailFeignClient emailFeignClient;

    @Resource
    private TblCountryMapper tblCountryMapper;

    /**
     * 全局变量
     */
    private String hashedPinCode = "";

    /**
     * 获取 Pin 码迭代
     *
     * @param accoutId 用户id
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Integer getPinCodeIteration(String accoutId) {
        Integer i = tblMemberMapper.getPinCodeInfo(accoutId);
        if (ObjectUtil.isNotEmpty(i)) {
            // 如果PinCode迭代次数大于0，则返回迭代次数和哈希PinCode
            if (i > 0) {
                hashedPinCode = String.valueOf(i);
            }
            return i;
        } else {
            return -99;
        }
    }

    @Override
    public ResponseResultApp updateProfile(UpdateProfileDto dto) throws Exception {
        TblMember member = UserUtil.getCurLoginMember();
        //校验字段值 - 这里做的是越南的校验
        if (ObjectUtil.isNotEmpty(dto.getPhone_country_id()) && dto.getPhone_country_id().equals("245") && ObjectUtil.isNotEmpty(dto.getOtp_code())) {
            Integer passwordIteration = getPinCodeIteration(member.getId());
            Boolean checkPinCode = false;
            if (passwordIteration > 0) {
                //检查密码
                checkPinCode = PBKDF2Util.verifyPassword(dto.getOtp_code(), member.getIterationPassword(), hashedPinCode);
            }
            if (!checkPinCode) {
                //对方返回：return new ApiResult(ErrorCodes.OTP_IS_INCORRECT, ErrorString.OTP_INVALID, null);
                return ResponseResultApp.error(400, "otp invalid");
            }
        }

        //定义最低年龄和最大年龄
        Integer minAge = 16, maxAge = 150;
        //调用工具类获取年龄
        Integer age = Kit.calculateAge(dto.getDate_of_birth(), "yyyy/MM/dd");
        if (ObjectUtil.isNotEmpty(age)) {
            //判断年龄
            if (age < minAge) {
                return ResponseResultApp.error(400, "You must be at least " + minAge + " years old to register an account");
            } else if (age > maxAge) {
                return ResponseResultApp.error(400, "Age should be less than " + maxAge + " years old");
            } else {
                if (ObjectUtil.isEmpty(dto.getEmail())) {
                    return ResponseResultApp.error(400, "Email must be filled in");
                }
                //检查 - 如果传入的参数和member的值不同则进入检查
                if (ObjectUtil.isNotEmpty(dto.getEmail()) && !member.getEmail().equals(dto.getEmail())) {
                    //检查邮箱是否存在
                    Integer byEmail = tblMemberMapper.findCheckByEmail(member.getId(), dto.getEmail());
                    if (byEmail > 0) {
                        return ResponseResultApp.error(400, "Email already exists");
                    }
                }
                if (ObjectUtil.isNotEmpty(dto.getNric_fin()) && !member.getNricFin().equals(dto.getNric_fin())) {
                    //检查身份证号
                    Integer byNricFin = tblMemberMapper.findCheckByNricFin(member.getId(), dto.getNric_fin());
                    if (byNricFin > 0) {
                        return ResponseResultApp.error(400, "NRIC FIN already exists");
                    }
                }
                if (ObjectUtil.isNotEmpty(dto.getPhone()) && !member.getPhone().equals(dto.getPhone())) {
                    //检查手机号
                    Integer byPhone = tblMemberMapper.findCheckByPhone(member.getId(), dto.getPhone());
                    if (byPhone > 0) {
                        return ResponseResultApp.error(400, "Phone number already exists");
                    }
                }

                //名称
                member.setFirstName(dto.getFirst_name() != null ? dto.getFirst_name() : member.getFirstName());
                if (ObjectUtil.isNotEmpty(dto.getLast_name())) {
                    member.setLastName(dto.getLast_name());
                }
                //身份证号
                member.setNricFin(dto.getNric_fin() != null ? dto.getNric_fin() : member.getNricFin());
                //性别
                if (ObjectUtil.isNotEmpty(dto.getGender()) && !member.getGender().equals(dto.getGender())) {
                    member.setGender(dto.getGender());
                }

                //生日
                if (ObjectUtil.isNotEmpty(dto.getDate_of_birth())) {
                    member.setDob(Kit.convertToDate(dto.getDate_of_birth(), "yyyy/MM/dd"));
                }


                //检查验证码为空 并且（传入的手机号不等于当前用户手机号 or 传入的手机号所在国家不等于当前用户的国家） - 返回错误信息
                if (ObjectUtil.isEmpty(dto.getOtp_code()) && (!member.getPhone().equals(dto.getPhone()) || !member.getPhoneCountryId().equals(dto.getPhone_country_id()))) {
                    //发送邮件
                    //传入的邮箱不为空 - 并且不等于当前用户的邮箱
                    if (ObjectUtil.isNotEmpty(dto.getEmail()) && !member.getEmail().equals(dto.getEmail())) {
                        //检查redis
                        String redisToken = JedisUtil.get(RedisEnum.UPDATE_EMAIL.getKey() + member.getId(), CodeEnum.REDIS_UPDATE_PROFILE.codeOf());
                        //存在则通过token的值去删除redis
                        if (ObjectUtil.isNotEmpty(redisToken)) {
                            //删除
                            JedisUtil.del(redisToken, CodeEnum.REDIS_UPDATE_PROFILE.codeOf());
                        }
                        //token定义为uuid
                        String uuid = Kit.get32UUID();
                        //存入redis - key：updateEmail:memberId,value:uuid
                        JedisUtil.set(RedisEnum.UPDATE_EMAIL.getKey(), uuid, CodeEnum.REDIS_UPDATE_PROFILE.codeOf());
                        //准备存入redis 的对象，key:uuid,value:对象转json
                        RedisMemberUpdateEmail redisMemberUpdateEmail = new RedisMemberUpdateEmail();
                        redisMemberUpdateEmail.setId(member.getId());
                        redisMemberUpdateEmail.setEmail(dto.getEmail());
                        //使用alibaba转换对象为json字符串
                        String jsonString = JSON.toJSONString(redisMemberUpdateEmail);
                        //存入redis
                        JedisUtil.set(uuid, jsonString, CodeEnum.REDIS_UPDATE_PROFILE.codeOf());
                        //发送邮件
                        Map<String, Object> map = new HashMap<>();
                        //todo - 这里地址后续需要更改
                        map.put("VerifyURL", "https://whcapi-qa.whitecoat.global/v1/VerifyEmailAddress?key=" + uuid);
                        map.put("EmailAddress", dto.getEmail());
                        map.put("PatientName", member.getFirstName() + (member.getLastName() != null ? member.getLastName() : ""));
                        String templateContent = HtmlUtils.getTemplateContent("VerifyEmailAddress.ftl", map);
                        MailgunUtil.sendEmail(dto.getEmail(), "Verify Your Email Address", null, templateContent);
                    }
                }

                //如果未传入typeId - 设置默认值为1
                if (ObjectUtil.isEmpty(dto.getType_id())) {
                    //设置默认为身份证
                    dto.setType_id(MemberIDCardTypeEnum.NRIC_FIN.getCode());
                }
                InputStream inputStream = null;
                //类型
                //todo 校验是否传入图片
                if (MemberIDCardTypeEnum.NRIC_FIN.getCode().equals(dto.getType_id())) {
                    //身份证
                    //正面身份证照片 - 对方传入的是base64的图片
                    if (ObjectUtil.isNotEmpty(dto.getFront_identification_card_photo())) {
//                    dto.setFront_of_driving_license_str("front-of-driving-license-" + Kit.get32UUID() + ".jpg");
                        //不为空 - 转换图片流 - 上传s3服务器 - 得到最终的地址 - 设置进member
                        inputStream = Kit.convertBase64ImageToInputStream(dto.getFront_identification_card_photo());
                        //todo 上传图片 - 并且得到文件路径
                        //设置进member表
                    }
                    //背面身份证照片
                    if (ObjectUtil.isNotEmpty(dto.getBack_identification_card_photo())) {
                        //不为空 - 转换图片流 - 上传s3服务器 - 得到最终的地址 - 设置进member
                        inputStream = Kit.convertBase64ImageToInputStream(dto.getBack_identification_card_photo());

                    }
                } else if (MemberIDCardTypeEnum.PASSPORT.getCode().equals(dto.getType_id()) && ObjectUtil.isNotEmpty(dto.getPassport_photo())) {
                    //护照照片
                    //不为空 - 转换图片流 - 上传s3服务器 - 得到最终的地址 - 设置进member
                    inputStream = Kit.convertBase64ImageToInputStream(dto.getPassport_photo());

                } else if (MemberIDCardTypeEnum.BIRTH_CERTIFICATE.getCode().equals(dto.getType_id()) && ObjectUtil.isNotEmpty(dto.getBirth_certificate_photo())) {
                    //出生证明照片
                    //不为空 - 转换图片流 - 上传s3服务器 - 得到最终的地址 - 设置进member
                    inputStream = Kit.convertBase64ImageToInputStream(dto.getBirth_certificate_photo());

                } else if (MemberIDCardTypeEnum.DRIVING_LICENSE.getCode().equals(dto.getType_id()) && ObjectUtil.isNotEmpty(dto.getFront_of_driving_license_photo())) {
                    //驾驶执照正面照片
                    //不为空 - 转换图片流 - 上传s3服务器 - 得到最终的地址 - 设置进member
                    inputStream = Kit.convertBase64ImageToInputStream(dto.getFront_of_driving_license_photo());


                    //驾驶执照背面照片
                    if (ObjectUtil.isNotEmpty(dto.getBack_of_driving_license_photo())) {
                        //不为空 - 转换图片流 - 上传s3服务器 - 得到最终的地址 - 设置进member
                        inputStream = Kit.convertBase64ImageToInputStream(dto.getBack_of_driving_license_photo());

                    }
                } else if (MemberIDCardTypeEnum.CHILD_PHOTO.getCode().equals(dto.getType_id()) && ObjectUtil.isNotEmpty(dto.getChild_photo())) {
                    //儿童照片
                    //不为空 - 转换图片流 - 上传s3服务器 - 得到最终的地址 - 设置进member
                    inputStream = Kit.convertBase64ImageToInputStream(dto.getChild_photo());
                }


                //紧急联系人 - 名称 - 这里实际只需要校验一个字段就行，对方前端校验的是只要填写了一个就必须全填
                if (ObjectUtil.isNotEmpty(dto.getEmergency_first_name())) {
                    member.setEmergencyFirstName(dto.getEmergency_first_name());
                    //姓
                    if (ObjectUtil.isNotEmpty(dto.getEmergency_last_name())) {
                        member.setEmergencyLastName(dto.getEmergency_last_name());
                    }

                    //紧急联系人关系
                    if (ObjectUtil.isNotEmpty(dto.getEmergency_relationship())) {
                        member.setEmergencyRelationship(dto.getEmergency_relationship());
                    }

                    //紧急联系人所在国家
                    if (ObjectUtil.isNotEmpty(dto.getEmergency_country_id())) {
                        member.setEmergencyCountryId(dto.getEmergency_country_id());
                    }

                    //紧急联系人手机号
                    if (ObjectUtil.isNotEmpty(dto.getEmergency_phone())) {
                        member.setEmergencyPhone(dto.getEmergency_phone());
                    }
                }
                //修改不为空的字段 - 对方页面做的是只要填写了就不能再次置空
                tblMemberMapper.updateByPrimaryKeySelective(member);

                return ResponseResultApp.success("Your profile has been updated");
            }
        } else {
            return ResponseResultApp.error(400, "Date of birth is a required parameter");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResultApp verifyEmailAddress(String key) {
        String json = JedisUtil.get(key, CodeEnum.REDIS_UPDATE_PROFILE.codeOf());
        //校验 - 不存在则返回错误
        if (ObjectUtil.isEmpty(json)) {
            return ResponseResultApp.error(400, "illegal request");
        }

        //将redis的数据转换为对象
        RedisMemberUpdateEmail redisMemberUpdateEmail = JSON.parseObject(json, RedisMemberUpdateEmail.class);
        if (ObjectUtil.isNotEmpty(redisMemberUpdateEmail)
                && ObjectUtil.isNotEmpty(redisMemberUpdateEmail.getId())
                && ObjectUtil.isNotEmpty(redisMemberUpdateEmail.getEmail())) {
            //先检查
            Example example = new Example(TblMember.class);
            example.createCriteria()
                    .andEqualTo("id", redisMemberUpdateEmail.getId())
                    .andEqualTo("status", 1)
                    .andEqualTo("delFlag", 0);
            TblMember member = tblMemberMapper.selectOneByExample(example);
            if (ObjectUtil.isEmpty(member)) {
                return ResponseResultApp.error(400, "Data does not exist");
            }


            //修改member的邮箱 - 并且调用方法去获取这个邮箱有哪些匹配的优惠卷 - 并且发送优惠卷邮件
            member.setEmail(redisMemberUpdateEmail.getEmail());
            tblMemberMapper.updateByPrimaryKeySelective(member);

            //远程调用
            MatchingPremiumCouponsDto dto = new MatchingPremiumCouponsDto();
            dto.setId(member.getId());
            dto.setNricFin(member.getNricFin());
            //现在所在国家
            dto.setCountryId(member.getCurrentCountry());
            dto.setFullName(member.getFirstName() + member.getLastName() != null ? member.getLastName() : "");
            //查询货币符号
            TblCountry country = tblCountryMapper.selectByPrimaryKey(member.getCurrentCountry());
            dto.setCurrency(country.getCurrency());
            dto.setEmail(member.getEmail());
            //调用方法检查有哪些匹配的优惠卷并发送邮件
            emailFeignClient.queryAvailablePremiumCouponsByEmail(dto);

            //删除redis数据
            JedisUtil.del(key);

            return ResponseResultApp.success();
        }

        return ResponseResultApp.error(400, "Data does not exist");
    }
}
